package cl.xintec.utils.excel
{
   import com.as3xls.xls.ExcelFile;
   import com.as3xls.xls.Sheet;
   
   import flash.errors.IllegalOperationError;
   import flash.net.FileReference;
   import flash.utils.ByteArray;
   
   import mx.collections.ArrayCollection;
   import mx.collections.ICollectionView;
   import mx.collections.IViewCursor;
   import mx.collections.XMLListCollection;
   import mx.controls.DataGrid;
   import mx.messaging.SubscriptionInfo;
   
   
   /**
    *
    * Author: Andrés Lozada Mosto
    * Version: 0.1
    * Fecha release: 10/03/2009
    * Contacto: alfathenus@gmail.com
    *  
    * Clase que maneja la exportacion de elementos
    * a Excel.
    * 
    * Se utiliza el proyecto http://code.google.com/p/as3xls/ 
    * para la generacion de Excel.
    * 
    * Se necesita la version 10 de Flash player para realizar el correcto
    * guardado del archivo sin pasar por backend.
    * 
    * @example
    * <code>
    * private var flat:ArrayCollection = new ArrayCollection([
    *                              {nombre:"Andrés", apellido:"Sanchez"},
    *                              {nombre:"Mónica", apellido:"Sanchez"},
    *                              {nombre:"Agustina", apellido:"Sanchez"},
    *                              {nombre:"Pablo", apellido:"Sanchez"},
    *                              {nombre:"Magalí", apellido:"Sanchez"}
    *                              ]);
    * ExcelExporterUtil.dataGridExporter(this.dg, "prueba_excel.xls");
    * </code>
    * 
    * Lista de funciones
    * <list>
    *  dataGridExporter:       Exporta un datagrid a un excel de forma automatica
    *  export:             Exporta un listado de objetos
    * </list>
         *
    */

   public class ExcelExporterUtil
   {
      public function ExcelExporterUtil()
      {
         throw new IllegalOperationError("Class \"ExcelExporterUtil\" is static. You can't instance this");
      }
      
      //-----------------------------
      // Public function
      //-----------------------------
	  /**
	   * 
	   * Exporta los datos de un datagrid hacia un Excel.
	   * Toma el dataProvider del mismo y las columnas para su exportacion
	   * 
	   * @param dg          Referencia al datagrid
	   * @defaultName         Nombre default con el que se va a generar el archivo excel
	   * 
	   */
	  static public function dataGridExporter(dg:DataGrid, defaultName:String):void
	  {
		  if (dg == null || dg.dataProvider == null || defaultName == null || defaultName == "")
			  return;
		  
		  var cols:Number = 0;
		  var colsValues:Array = [];
		  var cantCols:Number = dg.columnCount;
		  var fieldT:String;
		  var headerT:String;
		  
		  // armo el listado de headers y variables para cada columna
		  for ( ; cols < cantCols; cols++)
		  {
			  headerT = (dg.columns[cols] as Object).headerText
			  fieldT = (dg.columns[cols] as Object).dataField;
			  if ( fieldT == null || fieldT == "" || headerT == null || headerT == "")
				  continue; 
			  colsValues.push({
				  header:headerT,
				  value:fieldT
			  });
		  }
		  
		  if ( colsValues.length == 0 )
			  return;
		  
		  ExcelExporterUtil.export(dg.dataProvider, colsValues, defaultName);
	  }
	  
	  
	  
	  /**
	   * 
	   * Exporta los datos de un datagrid hacia un Excel.
	   * Toma el dataProvider del mismo y las columnas para su exportacion
	   * 
	   * @param dg          Referencia al datagrid
	   * @defaultName         Nombre default con el que se va a generar el archivo excel
	   * 
	   */
	  static public function dataGridExporterCSV(dg:DataGrid, defaultName:String):void
	  {
		  if (dg == null || dg.dataProvider == null || defaultName == null || defaultName == "")
			  return;
		  
		  var cols:Number = 0;
		  var colsValues:Array = [];
		  var cantCols:Number = dg.columnCount;
		  var fieldT:String;
		  var headerT:String;
		  
		  // armo el listado de headers y variables para cada columna
		  for ( ; cols < cantCols; cols++)
		  {
			  headerT = (dg.columns[cols] as Object).headerText
			  fieldT = (dg.columns[cols] as Object).dataField;
			  if ( fieldT == null || fieldT == "" || headerT == null || headerT == "")
				  continue; 
			  colsValues.push({
				  header:headerT,
				  value:fieldT
			  });
		  }
		  
		  if ( colsValues.length == 0 )
			  return;
		  
		  ExcelExporterUtil.exportCSV(dg.dataProvider, colsValues, defaultName);
	  }
	  
      /**
       * 
       * Export to Excell
       * 
       * @param obj          Objeto simple, XML, XMLList, Array, ArrayCollection o XMLListCollection
       *                   que se quiere exportar a excel
       * @colsValues         Listado de objetos que indican cual es el nombre de la columna
       *                   y que propiedad del objeto se utiliza para sacar los datos de la columna
       *                   {header:"nombre del header", value:"propiedad del objeto que contiene el valor"}
       * @param defaultName   Nombre default con el que se genera el excel
       * 
       */
      static public function export(obj:Object, colsValues:Array, defautlName:String):void
      {
         var _dp:ICollectionView = ExcelExporterUtil.getDataProviderCollection(obj);
         if ( _dp == null )
            return;
         
         var rows:Number = 0;
         var cols:Number = 0;
         var cantCols:Number = colsValues.length;
         var sheet:Sheet = new Sheet();
         sheet.resize(_dp.length, colsValues.length);
         
         for ( ; cols < cantCols; cols++)
         {
            sheet.setCell(rows, cols, colsValues[cols].header);
         }
         
         cols = 0;
         rows++;
         var cursor:IViewCursor = _dp.createCursor();
         while ( !cursor.afterLast )
         {
            for (cols = 0 ; cols < cantCols; cols++)
            {
               if ( (cursor.current as Object).hasOwnProperty(colsValues[cols].value) )
                     sheet.setCell(rows, cols, (cursor.current as Object)[colsValues[cols].value]);
            }
            
            rows++;
            cursor.moveNext();
         }
         
         var xls:ExcelFile = new ExcelFile();
         xls.sheets.addItem(sheet);
         var bytes:ByteArray = xls.saveToByteArray();
		 
         var fr:FileReference = new FileReference();
        //	fr.save(bytes, defautlName);
      }
      
	  
	  
	  
	  /**
	   * 
	   * Export to Excell
	   * 
	   * @param obj          Objeto simple, XML, XMLList, Array, ArrayCollection o XMLListCollection
	   *                   que se quiere exportar a excel
	   * @colsValues         Listado de objetos que indican cual es el nombre de la columna
	   *                   y que propiedad del objeto se utiliza para sacar los datos de la columna
	   *                   {header:"nombre del header", value:"propiedad del objeto que contiene el valor"}
	   * @param defaultName   Nombre default con el que se genera el excel
	   * 
	   */
	  static public function exportCSV(obj:Object, colsValues:Array, defautlName:String):void
	  {
		  var _dp:ICollectionView = ExcelExporterUtil.getDataProviderCollection(obj);
		  if ( _dp == null )
			  return;
		  
		  var rows:Number = 0;
		  var cols:Number = 0;
		  var cantCols:Number = colsValues.length;
	
		  
		 
		  cols = 0;
		  rows++;
		  var cursor:IViewCursor = _dp.createCursor();
		  
			var cuertpo:String;
			var bytes:ByteArray = new ByteArray();
			for ( ; cols < cantCols; cols++)
			{
				bytes.writeUTFBytes( colsValues[cols].header +"|"  );
			}
			bytes.writeUTFBytes("\n" );
		  while ( !cursor.afterLast )
		  {
			  
			  for (cols = 0 ; cols < cantCols; cols++)
			  {
				  
			  
			  
				  if ( (cursor.current as Object).hasOwnProperty(colsValues[cols].value) )
				  {
					  if(colsValues[cols].value=="FECHA")
					  {
						  var fecha:String;
						  fecha=(cursor.current as Object)[colsValues[cols].value];
						  /*var date:String = String(fecha.getDate());
						  if (date.length < 2)
							  date = "0" + date;
						  
						  var month:String = String(fecha.getMonth() + 1);
						  if (month.length < 2)
							  month = "0" + month;
						  
						  var year:String = String(fecha.getFullYear());*/
						  bytes.writeUTFBytes( fecha.substr(6,2)+"/"+fecha.substr(4,2)+"/"+ fecha.substr(0,4)+"|" );
					  }
					  else
					  {
						  if((cursor.current as Object)[colsValues[cols].value] == 'imagen/cross.png')
							  bytes.writeUTFBytes('X'+"|" );
						  else if((cursor.current as Object)[colsValues[cols].value] == 'imagen/tick.png')
							  bytes.writeUTFBytes('OK'+"|" );
						  else if((cursor.current as Object)[colsValues[cols].value] == 'imagen/bullet_white.png')
							  bytes.writeUTFBytes(''+"|" );
						  else
					  		  bytes.writeUTFBytes((cursor.current as Object)[colsValues[cols].value] +"|" );
					  
					  }
				  }
			  }
			  bytes.writeUTFBytes("\n" );
			  rows++;
			  cursor.moveNext();
		  }
		  
		//  var xls:ExcelFile = new ExcelFile();
		 // xls.sheets.addItem(sheet);
		  
		  
		  
		  
		  var fr:FileReference = new FileReference();
		  fr.save(bytes, defautlName);
	  }
	  
	  
	  
	  
	   
      //-----------------------------
      // Private function
      //-----------------------------
      /**
       * 
       * A partir de un elemento pasado se genera un ICollectionView
       * para su correcto recorrido
       * 
       * @param obj         Objeto a convertir a ICollectionView
       * 
       * 
       * @return referencia a un ICollectionView. 
       * 
       */
      static private function getDataProviderCollection(obj:Object):ICollectionView
      {
         if ( (obj is Number && isNaN(obj as Number)) || (!(obj is Number) && obj == null))
         {
            return null;
         }
         else if ( obj is ICollectionView )
         {
            return obj as ICollectionView;
         }
         else if ( obj is Array )
         {
            return new ArrayCollection(obj as Array);
         }
         else if ( obj is XMLList )
         {
            return new XMLListCollection(obj as XMLList);
         }
         else if ( obj is XML )
         {
            var col:XMLListCollection = new XMLListCollection();
            col.addItem(obj);
            return col;
         }
         else if ( obj is Object )
         {
            return new ArrayCollection([obj]);
         }
         else
         {
            return null;
         }
      }
   }
}